package translinkApp.DialogBoxes.ResolveLocation;

import java.io.IOException;
import java.util.ArrayList;

import translinkApp.Activities.MapViewActivity;
import translinkApp.Activities.R;
import translinkApp.Adaptors.Contacts.ContactAddressAdaptor;
import translinkApp.Adaptors.Contacts.ContactAddressListAdaptor;
import translinkApp.Data.ResolvedLocation.ResolvedLocation;
import translinkApp.Data.Utils.Functions;
import translinkApp.DataTypes.Contacts.ContactAddress;
import translinkApp.DataTypes.Contacts.ContactAddressList;
import translinkApp.DataTypes.Contacts.ContactAddresses;
import translinkApp.DataTypes.Threads.ErrorObject;
import translinkApp.DataTypes.Threads.ProgressAsyncTask;
import translinkApp.DialogBoxes.ResolveLocation.MyLocation.LocationResult;
import translinkApp.DialogBoxes.SavedLocations.OnReturnLocationListener;
import translinkApp.DialogBoxes.SavedLocations.SavedLocationsDialog;
import translinkApp.Utilities.Utils;
import translinkApp.views.dialog.LachDialog;
import translinkApp.views.dialog.LachDialogArguments;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;

public class ResolveLocationDialog extends LachDialog<ResolveLocationDialogData> {

	private final EditText locationEditText;
	private final RadioButton streetRadioButton;
	private ResolvedLocation resolvedLocation;

	private LocationListener listener;
	private LocationManager manager;
	private boolean fromLocation;
	private boolean automaticKeyboard;
	private ArrayList<ContactAddressList> contactAddresses;
	private Context context;
	private RadioButton suburbRadioButton;

	public ResolvedLocation getResolvedLocation() {
		return resolvedLocation;
	}

	public ResolveLocationDialog(Context context, LachDialogArguments args,
			ResolveLocationDialogData data) {
		super(context, R.layout.resolvelocationdialog, args, data);
		manager = (LocationManager) getContext().getSystemService(Activity.LOCATION_SERVICE);

		this.context = context;

		this.fromLocation = (Boolean) args.getArg(0);
		this.setContentView(R.layout.resolvelocationdialog);

		setTitle("Please enter a location to find:");

		locationEditText = (EditText) findViewById(R.id.locationDialogLocation);
		locationEditText.setOnFocusChangeListener(locationTextChangeListener);

		Button findButton = (Button) findViewById(R.id.locationDialogFind);
		findButton.setOnClickListener(findButtonListener);

		Button cancelButton = (Button) findViewById(R.id.locationDialogCancel);
		cancelButton.setOnClickListener(cancelButtonListener);

		Button locationButton = (Button) findViewById(R.id.locationDialogLocationButton);
		locationButton.setOnClickListener(locationButtonListener);

		Button savedButton = (Button) findViewById(R.id.locationDialogSavedButton);
		savedButton.setOnClickListener(savedButtonListener);

		Button mapViewButton = (Button) findViewById(R.id.locationDialogMapButton);
		mapViewButton.setOnClickListener(mapViewButtonListener);

		Button contactsButton = (Button) findViewById(R.id.locationDialogContacts);
		contactsButton.setOnClickListener(contactsButtonListener);

		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
		automaticKeyboard = prefs.getBoolean("AutomaticKeyboard", false);

		streetRadioButton = (RadioButton) findViewById(R.id.locationDialogfromStreetRadioButton);
		suburbRadioButton = (RadioButton) findViewById(R.id.fromLocationRadioButton);

		loadDialogData(data);

	}

	@Override
	public ResolveLocationDialogData getDialogData() {
		return new ResolveLocationDialogData(locationEditText.getText().toString(),
				streetRadioButton.isChecked(), fromLocation);
	}

	@Override
	public void loadDialogData(ResolveLocationDialogData data) {
		if (data != null) {
			locationEditText.setText(data.getSearch());
			streetRadioButton.setChecked(data.isStreet());
			fromLocation = data.isFromLocation();
		}
	}

	public String getProvider() {

		Criteria criteria = new Criteria();
		criteria.setSpeedRequired(true);
		criteria.setAltitudeRequired(true);

		return manager.getBestProvider(criteria, true);
	}

	View.OnFocusChangeListener locationTextChangeListener = new View.OnFocusChangeListener() {

		@Override
		public void onFocusChange(View v, boolean hasFocus) {
			if (automaticKeyboard) {
				if (hasFocus) {
					getWindow().setSoftInputMode(
							WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
				}
			}
		}
	};

	View.OnClickListener cancelButtonListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			removeGpsListener();
			cancel();
		}
	};

	View.OnClickListener locationButtonListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			try {
				removeGpsListener();

				AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
				builder.setMessage("Your location?");
				builder.setCancelable(true);
				builder.setPositiveButton("Refresh", new DialogInterface.OnClickListener() {
					public void onClick(final DialogInterface dialog, int id) {

						final ProgressDialog progress = ProgressDialog.show(context,
								"Please wait...", "Updating your location", true, true);

						MyLocation myLocation = new MyLocation();
						myLocation.getLocation(getContext(), progress, new LocationResult() {
							@Override
							public void gotLocation(final Location location) {
								progress.dismiss();
								try {
									updateStreet(Functions.getFirstStreet(context, location));
								} catch (IOException e) {
									try {
										Utils.showAlertDialog(
												context,
												"There was an error interpreting the GPS data.\n"
														+ "Make sure you are connected to the Internet.");
									} catch (Exception ex) {

									}
								}
							}
						});
					}
				});
				builder.setNegativeButton("Use last", new DialogInterface.OnClickListener() {
					public void onClick(final DialogInterface dialog, int id) {
						new GetLastLocationTask(context).execute();

					}
				});
				AlertDialog alert = builder.create();
				alert.show();

			} catch (Exception e) {
				Utils.showAlertDialog(getContext(), e.getMessage());
			}
		}
	};

	View.OnClickListener savedButtonListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			removeGpsListener();
			CreateSavedList();
		}
	};

	View.OnClickListener contactsButtonListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {

			if (contactAddresses == null) {
				new GetContactsTask(getContext()).execute();
			} else {
				showContactsDialog();
			}
		}
	};

	View.OnClickListener mapViewButtonListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {

			Intent myIntent = new Intent(getContext(), MapViewActivity.class);
			myIntent.putExtra("location", locationEditText.getText().toString());

			Activity activity = ((Activity) context);

			activity.startActivityForResult(myIntent, 1);
		}
	};

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == 1) {
			if (resultCode == Activity.RESULT_OK) {
				if (data.getBooleanExtra(MapViewActivity.MapResultStreetStringKey, true)) {
					updateStreet(data.getStringExtra(MapViewActivity.MapResultStringKey));
				} else {
					String stopName = data.getStringExtra(MapViewActivity.MapResultStringKey);
					returnResolvedLocation(new ResolvedLocation(stopName, stopName, false));
				}
			}
		}
	}

	private void showContactsDialog() {
		AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
		builder.setTitle("Contacts");

		builder.setAdapter(new ContactAddressAdaptor(context, contactAddresses),
				new DialogInterface.OnClickListener() {

					public void onClick(DialogInterface dialog, int item) {
						final ContactAddressList selectedSearch = contactAddresses.get(item);

						if (selectedSearch.size() == 1) {
							updateStreet(selectedSearch.get(0).getFullAddress());
							return;
						}

						AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
						builder.setTitle("Select Address");

						ContactAddressListAdaptor contactAdaptor = new ContactAddressListAdaptor(
								getContext(), selectedSearch);
						builder.setAdapter(contactAdaptor, new DialogInterface.OnClickListener() {

							public void onClick(DialogInterface dialog, int item) {
								ContactAddress selectedAddress = selectedSearch.get(item);

								updateStreet(selectedAddress.getFullAddress());
							}

						});

						AlertDialog alert = builder.create();
						alert.show();

					}
				});

		AlertDialog alert = builder.create();
		alert.show();
	}

	View.OnClickListener findButtonListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			find();
		}
	};

	private void find() {
		FindLocation.find(context, locationEditText.getText().toString(),
				streetRadioButton.isChecked(), new OnReturnLocationListener() {

					@Override
					public void onReturnLocation(ResolvedLocation location) {
						returnResolvedLocation(location);

					}
				});
	}

	private void returnResolvedLocation(ResolvedLocation loc) {
		resolvedLocation = loc;
		this.dismiss();
	}

	public void CreateSavedList() {
		SavedLocationsDialog.showDialog(getContext(), new OnReturnLocationListener() {

			@Override
			public void onReturnLocation(ResolvedLocation location) {
				returnResolvedLocation(location);

			}
		});
	}

	public void updateStreet(String street) {

		if (street.contains("-")) {
			street = street.substring(street.indexOf("-") + 1);
		}

		updateField(street, true);
	}

	public void updateSuburb(String suburb) {

		updateField(suburb, false);
	}

	public void updateField(String streetOrSuburb, boolean isStreet) {
		locationEditText.setText(streetOrSuburb);
		if (isStreet)
			streetRadioButton.setChecked(true);
		else
			suburbRadioButton.setChecked(true);
		removeGpsListener();

		find();
	}

	public void removeGpsListener() {
		if (manager != null) {
			if (listener != null) {
				manager.removeUpdates(listener);
				listener = null;
			}
		}
	}

	private class GetLastLocationTask extends ProgressAsyncTask<String> {

		public GetLastLocationTask(Context c) {
			super(c, "Please wait...", "Getting the last known location");

		}

		protected ErrorObject<String> doInBackground(String... params) {
			ErrorObject<String> journeys = new ErrorObject<String>();

			try {
				journeys.setItem(Functions.getFirstStreet(getContext(),
						manager.getLastKnownLocation(getProvider())));
			} catch (Exception e) {
				journeys.setException(e);
			}
			removeGpsListener();
			return journeys;

		}

		protected void onPostExecute(ErrorObject<String> result) {
			super.onPostExecute(result);

			if (!result.hasException()) {

				updateStreet(result.getItem());

			} else {
				Utils.showAlertDialog(getContext(), result.getException().getMessage());

			}
		}
	}

	public class MyLocationListener implements LocationListener {

		public MyLocationListener() {

		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

		@Override
		public void onProviderEnabled(String provider) {
		}

		@Override
		public void onProviderDisabled(String provider) {
		}

		@Override
		public void onLocationChanged(final Location location) {
			try {

				updateStreet(Functions.getFirstStreet(getContext(), location));

			} catch (Exception e) {

				removeGpsListener();
				Utils.showAlertDialog(getContext(), e.getMessage());
			}

		}

	}

	private class GetContactsTask extends ProgressAsyncTask<ArrayList<ContactAddressList>> {

		public GetContactsTask(Context c) {
			super(c, "Please wait...", "Loading contacts");

		}

		protected ErrorObject<ArrayList<ContactAddressList>> doInBackground(String... params) {
			ErrorObject<ArrayList<ContactAddressList>> contacts = new ErrorObject<ArrayList<ContactAddressList>>();

			try {
				contacts.setItem(ContactAddresses.getContactAddresses(getContext()));
			} catch (Exception e) {
				contacts.setException(e);
			}

			return contacts;

		}

		protected void onPostExecute(ErrorObject<ArrayList<ContactAddressList>> result) {
			super.onPostExecute(result);

			if (!result.hasException()) {

				contactAddresses = result.getItem();
				showContactsDialog();

			} else {
				Utils.showAlertDialog(getContext(), result.getException().getMessage());

			}
		}
	}
}